﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.IO.IsolatedStorage;
using System.Net;
using System.Net.Http;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Xml;
using System.Xml.Serialization;
using SC2TV.Object;

namespace SC2TV.Tools
{
    public class Requester
    {
        private readonly Uri url;
        private HttpClientHandler handler;
        CookieContainer cookies = new CookieContainer();

        public Requester(string url)
        {
            if (DesignerProperties.IsInDesignTool) return;

            this.url = new Uri(url);
            string lastActivity, lastVisit, password, sessionHash, userID, drupalUID, drupalUser, SESS, noCache, chatToken;
            IsolatedStorageSettings.ApplicationSettings.TryGetValue("bb_lastactivity", out lastActivity);
            IsolatedStorageSettings.ApplicationSettings.TryGetValue("bb_lastvisit", out lastVisit);
            IsolatedStorageSettings.ApplicationSettings.TryGetValue("bb_password", out password);
            IsolatedStorageSettings.ApplicationSettings.TryGetValue("bb_sessionhash", out sessionHash);
            IsolatedStorageSettings.ApplicationSettings.TryGetValue("bb_userid", out userID);
            IsolatedStorageSettings.ApplicationSettings.TryGetValue("drupal_uid", out drupalUID);
            IsolatedStorageSettings.ApplicationSettings.TryGetValue("drupal_user", out drupalUser);
            IsolatedStorageSettings.ApplicationSettings.TryGetValue("SESS4a29996287c6a61196a9cfc443f0fdb3", out SESS);
            IsolatedStorageSettings.ApplicationSettings.TryGetValue("nocache", out noCache);
            IsolatedStorageSettings.ApplicationSettings.TryGetValue("chat_token", out chatToken);
            if (!String.IsNullOrEmpty(password))
            {
                cookies.Add(this.url, new Cookie("bb_lastactivity", lastActivity));
                cookies.Add(this.url, new Cookie("bb_lastvisit", lastVisit));
                cookies.Add(this.url, new Cookie("bb_password", password));
                cookies.Add(this.url, new Cookie("bb_sessionhash", sessionHash));
                cookies.Add(this.url, new Cookie("bb_userid", userID));
                cookies.Add(this.url, new Cookie("drupal_uid", drupalUID));
                cookies.Add(this.url, new Cookie("drupal_user", drupalUser));
                cookies.Add(this.url, new Cookie("SESS4a29996287c6a61196a9cfc443f0fdb3", SESS));
                cookies.Add(this.url, new Cookie("nocache", noCache));
            }
            if (!String.IsNullOrEmpty(chatToken))
                cookies.Add(this.url, new Cookie("chat_token", chatToken));
            handler = new HttpClientHandler { AllowAutoRedirect = true, UseCookies = true, CookieContainer = cookies, UseDefaultCredentials = false };

            if (handler.SupportsAutomaticDecompression)
                handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
        }

        public async Task<Response> Get()
        {
            if (DesignerProperties.IsInDesignTool) return new Response { StatusCode = HttpStatusCode.BadGateway };

            try
            {
                var client = new HttpClient(handler);
                client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "text/html");
                var response = await client.GetAsync(url);
                response.EnsureSuccessStatusCode();
                var cookieCollection = cookies.GetCookies(new Uri("http://any.sc2tv.ru"));
                var responseStream = await response.Content.ReadAsStreamAsync();
                using (var streamReader = new StreamReader(responseStream))
                {
                    var html = streamReader.ReadToEnd();
                    return new Response { Html = html, StatusCode = response.StatusCode, Cookies = cookieCollection };
                }

            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
                return new Response { StatusCode = HttpStatusCode.BadGateway };
            }
        }

        public async Task<Response> Post(IEnumerable<KeyValuePair<string, string>> body)
        {
            if (DesignerProperties.IsInDesignTool) return new Response();

            var client = new HttpClient(handler);
            client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/x-www-form-urlencoded");
            var encoded = new FormUrlEncodedContent(body);
            var response = await client.PostAsync(url, encoded);
            response.EnsureSuccessStatusCode();
            var cookieCollection = cookies.GetCookies(new Uri("http://any.sc2tv.ru"));
            var responseStream = await response.Content.ReadAsStreamAsync();
            using (var streamReader = new StreamReader(responseStream))
            {
                var html = streamReader.ReadToEnd();
                return new Response { Cookies = cookieCollection, Html = html, StatusCode = response.StatusCode };
            }
        }

        internal async Task<Response<TResponse>> GetJson<TResponse>()
        {
            if (DesignerProperties.IsInDesignTool) return new Response<TResponse>();

            try
            {
                var client = new HttpClient(handler);
                client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json");
                var response = await client.GetAsync(url);
                var cookieCollection = cookies.GetCookies(new Uri("http://chat.sc2tv.ru"));
                var json = await response.Content.ReadAsStringAsync();
                var result = new Serializer().Deserialize<TResponse>(json);
                return new Response<TResponse> { Item = result, Cookies = cookieCollection };
            }
            catch (Exception)
            {
                return new Response<TResponse>();
            }
        }

        internal async Task<Response<TResponse>> GetXml<TResponse>()
        {
            if (DesignerProperties.IsInDesignTool) return new Response<TResponse>();

            try
            {
                var client = new HttpClient(handler);
                var response = await client.GetAsync(url);
                var cookieCollection = cookies.GetCookies(new Uri("http://chat.sc2tv.ru"));
                var xml = await response.Content.ReadAsStringAsync();
                var result = new Serializer().DeserializeXml<TResponse>(xml);
                return new Response<TResponse> { Item = result, Cookies = cookieCollection };
            }
            catch (Exception)
            {
                return new Response<TResponse>();
            }
        }
    }

    public class Serializer
    {
        public string Serialize<T>(T item)
        {
            var ms = new MemoryStream();
            new DataContractJsonSerializer(typeof(T)).WriteObject(ms, item);
            return Encoding.UTF8.GetString(ms.ToArray(), 0, ms.ToArray().Length);
        }

        public T Deserialize<T>(String json)
        {
            var serializer = new DataContractJsonSerializer(typeof(T));
            var resultClass = (T)serializer.ReadObject(new MemoryStream(Encoding.UTF8.GetBytes(json)));
            return resultClass;
        }

        public T DeserializeXml<T>(string xml)
        {
            using (var stringReader = new StringReader(xml))
            {
                var xmlSerializer = new XmlSerializer(typeof(T));
                return (T)xmlSerializer.Deserialize(stringReader);
            }
        }

    }
}
